- @title = 'Ajax programming'
:textile
  h3. Ajax and HTTP programming
  
  Ajax ('Asynchronous JavaScript and XML') is a technique that allows JavaScript
  programs to fetch data from the server without refreshing the page. Essentially, all it
  means is that JavaScript programs can make HTTP requests and handle the response
  that comes back. XML does not have to be involved - the server can return whatever
  it likes, be that plain text, HTML, XML, JSON, CSV, whatever. It's up to your
  script to deal with whatever comes back.
  
  h3. Required files
  
  * @http://yui.yahooapis.com/2.6.0/build/yahoo-dom-event/yahoo-dom-event.js@
  * @http://yui.yahooapis.com/2.6.0/build/selector/selector-beta.js@
  * @http://yui.yahooapis.com/2.6.0/build/connection/connection.js@
  * @http://yoursite.com/ojay/js-class.js@
  * @http://yoursite.com/ojay/core.js@
  * @http://yoursite.com/ojay/pkg/http.js@
  
  h3. How to make requests
  
  This is trivially simple - you just use HTTP verbs to GET from/POST to URLs.
  
  <pre class="prettyprint">    Ojay.HTTP.GET('/index.html')</pre>
  
  The above code won't do anything interesting since we don't handle the response -
  we'll get to that in a minute. The second argument is a parameter list, used to
  build the query string or POST message for the request. Properties in the parameter
  list override those in the URL:
  
  <pre class="prettyprint">    Ojay.HTTP.GET('/index.html', {foo: 'bar', ajaxLayout: true})
      // -> GET /index.html?foo=bar&ajaxLayout=true
      
      Ojay.HTTP.GET('/index.html?foo=45', {foo: 23})
      // -> GET /index.html?foo=23
      
      Ojay.HTTP.POST('/submitForm.html', {name: 'Bob', email: '...'})
      // -> POST /submitForm.html
      //    message: name=Bob email=...</pre>
  
  h3. How to handle the response
  
  The final parameter is a set of callbacks that handle the response under various
  conditions. The available callbacks are:
  
  * @onSuccess@ - is fired if the response has a 2xx code
  * @onFailure@ - is fired if the response has a 3xx, 4xx or 5xx code
  * @onXXX@, where @XXX@ is an HTTP status code. e.g. @on404@ is fired if the reponse
    has a @404@ status code.
  
  Each callback is given the response object from the server, which Ojay adds some
  handy methods to to make life easier. These are:
  
  * @insertInto(elements, position)@ - inserts the response body into the given elements.
    @elements@ can be a CSS selector, and Ojay collection or a raw @HTMLElement@
    reference. Script tags in the response are removed.
    
  * @evalScripts()@ - evaluates any script blocks in the response body.
  
  Some examples:
  
  <pre class="prettyprint">    Ojay.HTTP.GET('/index.html', {}, {
        onSuccess: function(response) {
          response.insertInto('#myDiv');
          // ... other logic
        }
      });
      
      // If your server uses HTTP status codes to
      // describe the response, you can do this...
      
      Ojay.HTTP.POST('/doLogin.html', {name: '...', password: '...'}, {
        onSuccess: function(response) {
          // user logged in, so redirect...
          window.location.href = '/protected/user/area.html';
        },
        on403: function(response) {
          // login denied
          alert('You did not login');
        }
      });</pre>
  
  h3. Using @MethodChain@
  
  @GET()@ and @POST()@ both return "@MethodChain@":/articles/method_chain.html objects
  whose chain will fire on the @response@ object when it arrives from the server.
  That means you can do stuff like this:
  
  <pre class="prettyprint">    Ojay.HTTP.GET('/index.html').insertInto('div').evalScripts();
      
      // Make an Ajax call on click
      
      Ojay('a').on('click', Ojay.stopEvent)
          ._(Ojay.HTTP).GET('/gallery.html')
          .insertInto('#gallery');</pre>
  
  (Just for comparison, here's how to write the previous example in YUI:)
  
  <pre class="prettyprint">    (function() {
        var links = YAHOO.util.Selector.query('a');
        YAHOO.util.Event.addListener(links, 'click', function(e) {
          YAHOO.util.Event.preventDefault(e);
          YAHOO.util.Event.stopPropagation(e);
          YAHOO.util.Connect.asyncRequest('GET', '/gallery.html', {
            success: function(resp) {
              var elem = YAHOO.util.Selector.query('#gallery')[0];
              elem.innerHTML = resp.responseText;
            }
          });
        });
      })();</pre>
  
  You need to remember that these chains are asynchronous, though:
  
  <pre class="prettyprint">    var h1 = Ojay('h1#header');
      h1.setContent('Title');
      
      Ojay.HTTP.GET('/index.html').insertInto(h1);
      
      h1.node.innerHTML  // -> "Title"</pre>
  
  The @insertInto(h1)@ calls takes place whenever the response arrives from the server,
  and code execution does not halt while the browser is waiting for this response.
  
  h3. Cross-domain @GET@ and @POST@
  
  @GET@ and @POST@ can also be used cross-domain using @Ojay.HTTP@. To use cross-domain
  @GET@, you need to include YUI's @Get@ utility:
  
  * @http://yui.yahooapis.com/2.6.0/build/get/get.js@
  
  No additional files are required for cross-domain @POST@.
  
  Both these methods are designed for talking to web services, specifically those that
  publish JSON. If a web service allows you to specify a callback to pass data to, you
  can use the service like this:
  
  <pre class="prettyprint">    Ojay.HTTP.GET('http://example.com/posts/45.json', {
        user: 'your_username',
        api_key: '4567rthdtyue566w34',
        callback: 'handleJSON'
      });
      
      var handleJSON = function(json) {
        // process json object
      };</pre>
  
  This will inject a script tag into your page that calls your @handleJSON()@ function
  with the data from the service.
  
  Cross-domain POST works in a similar way, except you cannot use callbacks as same-origin
  restrictions mean there is no way to access the response from a cross-domain POST request.
  Still, you can send data to other sites easily:
  
  <pre class="prettyprint">    Ojay.HTTP.POST('http://example.com/posts/create', {
        user: 'your_username',
        api_key: '4567rthdtyue566w34',
        title: 'A new blog post',
        content: 'Lorem ipsum dolor sit amet...'
      });</pre>
  
  h3. Transparent JSON-P support
  
  Ojay lets you use the same API for cross-domain JSON-P calls as you'd use to talk to
  your own server. This means that, rather than explicitly naming a global data handler
  (as in the @handleJSON@ example above), you can use the standard Ajax syntax with
  anonymous callback functions. To do this, you just need to specify the name of the
  callback parameter used by the third-party JSON-P API. For example, the following
  service calls the JSON-P callback param @callback@:
  
  <pre class="prettyprint">    Ojay.HTTP.GET('http://json-time.appspot.com/time.json', {
        tz: 'America/Chicago',
        jsonp: 'callback'
      }, {
        onSuccess: function(data) {
          // handle data
        }
      });</pre>
  
  Remember that for cross-domain requests, the callback parameter will not be an
  @HTTP.Response@ object as it is for local requests. @data@ will be whatever native
  JavaScript object the third-party provides, typically a basic @Object@.
  
  h3. @GET@ and @POST@ redirects
  
  Ojay's HTTP package provides convenient methods for doing both @GET@- and @POST@-based
  redirects to other pages (on your domain or anywhere else), using the same parameter
  object syntax as you'd use for Ajax calls. Simply use them like this:
  
  <pre class="prettyprint">    Ojay.HTTP.GET.redirectTo('http://google.com/search', {
        q: 'javascript redirects'
      });
      
      Ojay.HTTP.POST.redirectTo('http://example.com/login', {
        username: 'someGuy',
        password: 'r67ge4546'
      });</pre>
  
  (@YAHOO.util.Get@ is not required for redirects, only for cross-domain Ajax-style @GET@).
  
  h3. HTTP events
  
  The @Ojay.HTTP@ object publishes a number of events that allow you to monitor HTTP
  activity initiated through Ojay. To listen to an event, you just need to specify the
  name of the event and a callback function, for example:
  
  <pre class="prettyprint">    Ojay.HTTP.on('request', function(req) {
          console.log(req.getURI().params);
      });</pre>
  
  The full list of event names is:
  
  * @request@ - fired whenever a request starts. The @HTTP.Request@ object is passed to the
    callback.
  * @complete@ - fired when a request finishes with any status code. Passes the @HTTP.Response@
    object to the callback.
  * @success@ - fired when a request completes with a 2xx status. Passes the @HTTP.Response@
    object to the callback.
  * @failure@ - fired when a request completes with a 3xx, 4xx or 5xx code. Passes the @HTTP.Response@
    object to the callback.
  
  You can also listen out for specific status codes as follows:
  
  <pre class="prettyprint">    // Listen for status-200 responses
      Ojay.HTTP.on(200, function(response) {
          alert('Successful request');
      });</pre>
